home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / util / cli / cw112.lha / CW.c next >
Encoding:
C/C++ Source or Header  |  1995-03-04  |  8.1 KB  |  284 lines

  1. /*************************************************************************
  2. **
  3. ** >>>> CW.c of Saturday, 04 Mar 1995 12:40:24
  4. **************************************************************************
  5. ** Zweck:
  6. **  Zählt die Anzahl der Worte, die auf <Word> passen.
  7. **  oder die Anzahl Zeilen, die auf <Pattern> passen.
  8. **
  9. **************************************************************************
  10. **
  11. ** History
  12. **
  13. ** Version  Datum         Aenderungen
  14. ** -------  -----------   ------------------------------------------------
  15.     1.0     24 Feb 1995   Siehe History File
  16.     1.1     24 Feb 1995   Siehe History File
  17.     1.2     24 Feb 1995   Siehe History File
  18.     1.3     24 Feb 1995   Siehe History File
  19.     1.4     02 Mar 1995   Siehe History File
  20.     1.5     02 Mar 1995   Siehe History File
  21.     1.6     02 Mar 1995   Siehe History File
  22.     1.7     02 Mar 1995   Siehe History File
  23.     1.8     02 Mar 1995   Siehe History File
  24.     1.9     02 Mar 1995   Siehe History File
  25.     1.10    02 Mar 1995   Siehe History File
  26.     1.11    02 Mar 1995   Siehe History File
  27.     1.12    04 Mar 1995   Siehe History File
  28.  
  29. **
  30. *** ts=2 ****************************************************************/
  31.  
  32.  
  33. #define __USE_SYSBASE aye
  34.  
  35. #include <exec/exec.h>
  36. #include <proto/exec.h>
  37.  
  38. #include <dos/dos.h>
  39. #include <proto/dos.h>
  40.  
  41. #include <string.h>
  42.  
  43. #include <own/CTRL-C.h>
  44.  
  45. const char  version[] = "\0$VER: CW 1.12 ("__DATE__"/"__TIME__")\0";
  46. const char *ver = &version[7];
  47.  
  48. struct args {
  49.   char  *arg_File;
  50.   char  *arg_Word;
  51.   ULONG  arg_IgnCase;
  52.   ULONG  arg_Quiet;
  53.   ULONG  arg_InBuf;
  54.   ULONG  arg_InBufDef;                 // Hier steht der Defaultwert für InBuf, hat nix mit ReadArgs zu tun.
  55. } Args = { NULL, NULL, FALSE, FALSE, 1000, 1000 };
  56.  
  57. const char template[] = "FILE/A,WORD/A,NC=NoCase/S,Q=Quiet/S,B=InBuf/N/K\n\0";
  58.  
  59. BOOL MNC(STRPTR, STRPTR);
  60. BOOL MC(STRPTR, STRPTR);
  61.  
  62. int PMatch(BPTR file, void *pat, BOOL (*func)(STRPTR, STRPTR));
  63. int WMatch(BPTR file);
  64.  
  65. int main(void)
  66. {
  67.   struct RDArgs *myrda;
  68.   BPTR   lock, fle;
  69.   char  *pattern;
  70.   int    fm, i;
  71.  
  72.   if(myrda = ReadArgs(template, (LONG *)&Args, NULL))
  73.   {
  74.  
  75.     if(Args.arg_InBufDef != Args.arg_InBuf) Args.arg_InBuf = *(ULONG *)Args.arg_InBuf;
  76.  
  77.     if(lock = Lock(Args.arg_File, ACCESS_READ))
  78.     {
  79.       fle = OpenFromLock(lock);
  80.       if(!fle)
  81.       {
  82.         PrintFault(IoErr(), "DOS");
  83.         UnLock(lock);
  84.         Printf("Konnte Suchfile %s nicht öffnen!\n", Args.arg_File);
  85.         return RETURN_FAIL;
  86.       }
  87.     }
  88.     else
  89.     {
  90.       PrintFault(IoErr(), "DOS");
  91.       UnLock(lock);
  92.       Printf("Konnte Suchfile %s nicht ansprechen!\n", Args.arg_File);
  93.       return RETURN_FAIL;
  94.     }
  95.  
  96.     if(pattern = AllocVec(3*strlen(Args.arg_Word), MEMF_ANY))
  97.     {
  98.       if(Args.arg_IgnCase)
  99.       {
  100.         if(ParsePatternNoCase(Args.arg_Word, pattern, 3*strlen(Args.arg_Word)))
  101.           fm = PMatch(fle, pattern, MNC);
  102.         else
  103.         {
  104.           for(i=0;i<strlen(Args.arg_Word); Args.arg_Word[i]=tolower(Args.arg_Word[i++]));
  105.           fm = WMatch(fle);
  106.         }
  107.       }
  108.       else
  109.       {
  110.         if(ParsePattern(Args.arg_Word, pattern, 3*strlen(Args.arg_Word)))
  111.           fm = PMatch(fle, pattern, MC);
  112.         else
  113.           fm = WMatch(fle);
  114.       }
  115.       Printf( ((Args.arg_Quiet) ? "%ld\n" : "\nMatches found: [%ld]\n\n"), fm);
  116.       FreeVec(pattern);
  117.     }
  118.  
  119.     Close(fle);
  120.   }
  121.   return RETURN_OK;
  122. }
  123.  
  124. BOOL MNC(STRPTR pat, STRPTR match)
  125. {
  126.   return MatchPatternNoCase(pat, match);
  127. }
  128.  
  129. BOOL MC(STRPTR pat, STRPTR match)
  130. {
  131.   return MatchPattern(pat, match);
  132. }
  133.  
  134. int PMatch(BPTR file, void *pat, BOOL (*func)(STRPTR, STRPTR))
  135. {
  136.   BOOL  goon = TRUE;
  137.   char *buf;
  138.   int   i = 0, k = 0;
  139.   ULONG sigs;
  140.  
  141.   if(buf = AllocVec(Args.arg_InBuf, MEMF_ANY|MEMF_CLEAR))
  142.   {
  143.     while(goon && !(sigs = CTRLC))
  144.     {
  145.       if(!Args.arg_Quiet) Printf("Scanning Line %ld, so far %ld.\r", ++k, i);                     // Ausgabe
  146.       goon = FGets(file, buf, Args.arg_InBuf);                     // Bei Fehler oder EOF Schleife abbrechen
  147.       if((goon) && (func(pat, buf))) i++;                            // Vergleichen, wenn nicht EOF erreicht
  148.     }
  149.  
  150.     FreeVec(buf);                                                               // Inbuffer wieder freigeben
  151.  
  152.     if(sigs)
  153.     {
  154.       Printf("\n*** BREAK!\n");
  155.       return i;
  156.     }
  157.  
  158.     if(IoErr())
  159.     {
  160.       PrintFault(IoErr(), "DOS");
  161.       Printf("Beim Scannen der Datei ist ein Fehler aufgetreten!\n");
  162.       return 0;
  163.     }
  164.   }
  165.   else
  166.   {
  167.     Printf( "Zu wenig Speicher für den Lesepuffer (%ld Bytes)!\n"
  168.             "Bitte modifizieren Sie die Größe mittels des <InBuf>-Parameters!\n", Args.arg_InBuf);
  169.     return 0;
  170.   }
  171.  
  172.   return i;
  173. }
  174.  
  175. int WMatch(BPTR file)
  176. {
  177.   BOOL  goon = TRUE;
  178.   char *chlut;
  179.   char *buf, c;
  180.   int   len, k, j, i, skip, buflen, cnt = 0;
  181.   ULONG sigs;
  182.  
  183.   if(buf = AllocVec(Args.arg_InBuf, MEMF_ANY|MEMF_CLEAR))
  184.   {
  185.     len = strlen(Args.arg_Word);
  186.  
  187.     if(chlut = AllocVec(255, MEMF_ANY))                        // Character LookUp Table erzeugen
  188.     {
  189.       for(i=0; i<255; chlut[i++]=len);                                         // Alle Zeichen !e Word = len
  190.       for(i=1; i<=len; chlut[Args.arg_Word[i-1]]=len-i++);     // Zeichen e Word mit dem Abstand zum, Wortende
  191.     }
  192.     else
  193.     {
  194.       FreeVec(buf);
  195.       Printf("Nicht genug freier Speicher für die Character LUT!\n");
  196.       return 0;
  197.     }
  198.  
  199.     k=0;
  200.     while(goon)
  201.     {
  202.       goon = FGets(file, buf, Args.arg_InBuf);                     // Bei Fehler oder EOF Schleife abbrechen
  203.  
  204.       if(!Args.arg_Quiet) Printf("Scanning Line %ld, so far %ld.\r", ++k, cnt);                   // Ausgabe
  205.  
  206.       if(goon)
  207.       {
  208.         buflen = strlen(buf);
  209.  
  210.         if(Args.arg_IgnCase) for(i=0;i<buflen; buf[i]=tolower(buf[i++]));   // Zeile in LoCase, wenn IgnCase
  211.  
  212.         j=len-1;
  213.         while(j < buflen)                                                    // Bin ich noch im Buffer?
  214.         {
  215.           i=len;
  216.           while((i) && (j < buflen) && !(sigs = CTRLC))             // Bin ich noch im Buffer?, CTRL-C gedrückt?
  217.           {
  218.             c = buf[j];
  219.             if(Args.arg_Word[i-1] == c)
  220.             {
  221.               i--;                                                          // Ein Zeichen vornedran checken
  222.               j--;
  223.             }
  224.             else
  225.             {
  226.               skip = chlut[c];
  227.  
  228. /*
  229. ** Diese Abfrage hat mich schwer aufgehalten. Alle Zeichen, die Teil des Wortes sind, und rechts von dem
  230. ** fehlgeschlagenen Vergleich stehen, sind Teil des Wortes und damit bereits vorgekommen. Es kann daher nur
  231. ** sein, daß das Muster nach rechts verschoben werden kann um zu passen. Zeichen die eine Verschiebung des
  232. ** Musters sinnvoll machen, müssen daher von Rechts des Fehlschlags stammen. Die chlut[] Werte rechts des
  233. ** Fehlschlages sind größer oder gleich len-i+1, links davon sind alle kleiner len-i+1!
  234. ** Einfach und genial!
  235. ** HALL in "HALLL" kann nicht zum Problem werden, da HALL bereits gefunden wird, bevor der Zeiger auf das
  236. ** dritte "l" springt! Kein Wort wird komplett übersprungen.
  237. */
  238.  
  239.               if(len-i+1 > skip)
  240.                 j += len - i + 1;                  // Index an Wordende des nächsten möglichen Wortes setzen
  241.               else
  242.                 j += skip;                                                        // Buchstaben überspringen
  243.  
  244.               i = len;                                                   // Vergleich wieder vom Wortende an
  245.             }
  246.           }
  247.  
  248.           if(sigs)
  249.           {
  250.             Printf("\n*** BREAK!\n");
  251.             FreeVec(chlut);
  252.             FreeVec(buf);
  253.             return cnt;
  254.           }
  255.  
  256.           if(!i)
  257.           {
  258.             cnt++;                              // Wenn i auf Null gewandert ist, hab ich ein Wort gefunden!
  259.             j+=2*len;                               // j auf das Zeichen hinter den gefundenen String setzen
  260.           }
  261.         }
  262.       }
  263.     }
  264.  
  265.     if(IoErr())
  266.     {
  267.       PrintFault(IoErr(), "DOS");
  268.       Printf("Beim Scannen der Datei ist ein Fehler aufgetreten!\n");
  269.       return 0;
  270.     }
  271.  
  272.     FreeVec(chlut);
  273.     FreeVec(buf);
  274.   }
  275.   else
  276.   {
  277.     Printf( "Zu wenig Speicher für den Lesepuffer (%ld Bytes)!\n"
  278.             "Bitte modifizieren Sie die Größe mittels des <InBuf>-Parameters!\n", Args.arg_InBuf);
  279.     return 0;
  280.   }
  281.  
  282.   return cnt;
  283. }
  284.